背景介绍
Kubernetes将集群中的机器划分为单个Master和多个Node。
Master上运行集群管理相关的进程,实现整个集群的资源管理、Pod调度、弹性伸缩、安全控制、系统监控和纠错等管理的自动完成功能,如kube-apiserver、kube-controller-manager、kubescheduler、etcd
Node是工作节点,运行真正的应用,其最小运行单元是Pod,POD相当于一个容器,有独立的ip、hostname,通过namespace进行资源隔离,独立沙箱环境;一个Pod包含调用链上的一组容器,一个pod内部的多个容器,共享一个pause容器;同时一个pod中的不同容器间通过localhost访问。Node上运行kubelet、kube-proxy
服务进程来负责Pod的创建、启动、监控、重启、销毁,及实现软件模式的负载均衡器。POD有生命周,有宕机、版本更新的情况,会创建新的pod,ip及hostname会发生变化。
针对服务的容器化部署,主要涉及2类:
StatefulSet:解决有状态服务使用容器化部署
deployment:解决无状态服务的容器化部署
Service资源对象
POD IP :pod的ip地址,其上层是pod网关,同网段的pod之间通过该IP进行路由分发
Cluster IP:虚拟IP(VIP),由k8s抽象出的service对象
Node IP :物理机IP地址
Service VIP:
1、service与pod都是进程(非物理硬件),service也不能对外网提供服务;
2、service与pod之间可以直接进行通信,它们的通信属局域网通信
3、把请求交给service后,service使用iptables/ipvs进行数据包的分发
将pod绑定物理端口:物理机IP+端口--->Service VIP---> 通过iptables/ipvs进行数据包转发
service对象 通过“标签选择器”关联一组pod,如果POD出现宕机、版本更新,每个节点上的kube-proxy会监听pod的存活状态,然后更新VIP到endpoints的映射关系,该映射关系存储在etcd中
实际操作
机器配置要求
每台机器 2 GB 或更多的 RAM
2 核CPU 或更多
安装的步骤流程图

前期准备工作
kubeadm是Kubernetes官方提供的用于快速安装Kubernetes集群的工具,在安装前,先满足如下条件:
(1)集群中的所有机器的网络互通
(2)集群中的所有机器主机名、MAC 地址或 uuid唯一
针对product_uuid 校验:
cat /sys/class/dmi/id/product_uuid
(3)禁用交换分区:swapoff -a
(4)关闭防火墙以及selinux
systemctl stop firewalld && systemctl disable firewalldyum -y install iptables-services && systemctl start iptables && systemctl enable iptables && iptables -F && service iptables savesetenforce 0sed -i "s/SELINUX=enforcing/SELINUX=disabled/g" /etc/selinux/config
(5)修改主机名及时区,确保集群中各节点不同主机名、相同时区:
hostnamectl set-hostname masterecho "127.0.0.1 $(hostname)" >> /etc/hoststimedatectl set-timezone Asia/Shanghai
(6)持久化journal日志,非必要。可以参考:https://blog.steamedfish.org/post/systemd-journald/
mkdir /etc/systemd/journald.conf.d && mkdir /var/log/journalcat > /etc/systemd/journald.conf.d/99-prophet.conf <<EOF[Journal]Storage=persistentCompress=yesSyncIntervalSec=5mRateLimitInterval=30sRateLimitBurst=1000SystemMaxUse=2GSystemMaxFileSize=200MMaxRetentionSec=2weekForwardToSyslog=noEOFsystemctl restart systemd-journald
(7)安装docker
针对iptables被绕过而导致流量无法正确路由的问题,可以设置sysctl
配置中的 net.bridge.bridge-nf-call-iptables
被设置为1。
modprobe br_netfiltercat > /etc/sysctl.d/99-kubernetes-cri.conf <<EOFnet.bridge.bridge-nf-call-iptables = 1net.ipv4.ip_forward = 1net.bridge.bridge-nf-call-ip6tables = 1vm.swappiness=0EOFsysctl --system
可以使用
lsmod |grep br_netfilter
查看模块是否有正常加载。再运行安装docker,设置aliyun源:
yum install yum-utils device-mapper-persistent-data lvm2 -yyum-config-manager --add-repo http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repoyum install containerd.io-1.2.10 docker-ce-19.03.4 docker-ce-cli-19.03.4 -ysystemctl start dockercat > /etc/docker/daemon.json <<EOF{"registry-mirrors": ["https://registry.cn-hangzhou.aliyuncs.com"],"exec-opts": ["native.cgroupdriver=systemd"],"log-driver": "json-file","log-opts": {"max-size": "100m"},"storage-driver": "overlay2","storage-opts": ["overlay2.override_kernel_check=true"]}EOFmkdir -p /etc/systemd/system/docker.service.dsystemctl enable docker && systemctl daemon-reload && systemctl restart docker
使用systemd作为docker的cgroup driver可确保服务器节点在资源紧张的情况更稳定,因此这里修改各个节点上docker的cgroup driver为systemd。即:native.cgroupdriver=systemd
安装k8s工具
需要在集群中的每个节点上安装以下的软件包:
kubeadm
:用来初始化集群的指令。kubelet
:在集群中的每个节点上用来启动 pod 和容器等,是一个持续运行的后台服务。kubectl
:用来与集群通信的命令行工具。
(8.1)先配置K8S的yum源
cat <<EOF > /etc/yum.repos.d/kubernetes.repo[kubernetes]name=Kubernetesbaseurl=http://mirrors.aliyun.com/kubernetes/yum/repos/kubernetes-el7-x86_64enabled=1gpgcheck=0repo_gpgcheck=0gpgkey=http://mirrors.aliyun.com/kubernetes/yum/doc/yum-key.gpghttp://mirrors.aliyun.com/kubernetes/yum/doc/rpm-package-key.gpgEOF
(8.2)使用yum list kubelet --showduplicates
来查看可用的版本,默认可以直接进行安装:
yum install -y kubelet kubeadm kubectl --disableexcludes=kubernetessystemctl enable --now kubelet# yum install -y ipvsadm bash-completion 无法直接安装的情况下使用如下4行wget http://mirror.centos.org/altarch/7/os/armhfp/Packages/bash-completion-2.1-8.el7.noarch.rpmrpm -ivh bash-completion-2.1-8.el7.noarch.rpmwget http://mirror.centos.org/centos/7/os/x86_64/Packages/ipvsadm-1.27-8.el7.x86_64.rpmrpm -ivh ipvsadm-1.27-8.el7.x86_64.rpmmkdir ~/.kube/kubectl completion bash > ~/.kube/completion.bash.incprintf "# Kubectl shell completionsource '$HOME/.kube/completion.bash.inc'" >> $HOME/.bash_profilesource $HOME/.bash_profileecho 'alias k=kubectl' >>~/.bashrcecho 'complete -F __start_kubectl k' >>~/.bashrcsource ~/.bashrc
(8.3)加载ipvs模块:使用ipvs模块替代iptables,性能更好,但不是必须。
cat > /etc/sysconfig/modules/ipvs.modules <<EOF#!/bin/bashmodprobe -- br_netfiltermodprobe -- ip_vsmodprobe -- ip_vs_rrmodprobe -- ip_vs_wrrmodprobe -- ip_vs_shmodprobe -- nf_conntrack_ipv4EOFchmod 755 /etc/sysconfig/modules/ipvs.modules && \bash /etc/sysconfig/modules/ipvs.modules && \lsmod | grep -E "ip_vs|nf_conntrack_ipv4"
手工下载k8s镜像
总体思路是使用 kubeadm config images list
先输出镜像名,然后替换为阿里源:
k8s.gcr.io/kube-apiserver:v1.18.3k8s.gcr.io/kube-controller-manager:v1.18.3k8s.gcr.io/kube-scheduler:v1.18.3k8s.gcr.io/kube-proxy:v1.18.3k8s.gcr.io/pause:3.2k8s.gcr.io/etcd:3.4.3-0k8s.gcr.io/coredns:1.6.7
具体镜像下载脚本如下:
#!/bin/bashkube_version=:v1.18.3kube_images=(kube-proxy kube-scheduler kube-controller-manager kube-apiserver)addon_images=(etcd-amd64:3.4.3 coredns:1.6.7 pause-amd64:3.2)for imageName in ${kube_images[@]} ;dodocker pull registry.cn-hangzhou.aliyuncs.com/google_containers/$imageName-amd64$kube_versiondocker image tag registry.cn-hangzhou.aliyuncs.com/google_containers/$imageName-amd64$kube_version k8s.gcr.io/$imageName$kube_versiondocker image rm registry.cn-hangzhou.aliyuncs.com/google_containers/$imageName-amd64$kube_versiondonefor imageName in ${addon_images[@]} ;dodocker pull registry.cn-hangzhou.aliyuncs.com/google_containers/$imageNamedocker image tag registry.cn-hangzhou.aliyuncs.com/google_containers/$imageName k8s.gcr.io/$imageNamedocker image rm registry.cn-hangzhou.aliyuncs.com/google_containers/$imageNamedonedocker tag k8s.gcr.io/etcd-amd64:3.4.3 k8s.gcr.io/etcd:3.4.3-0docker image rm k8s.gcr.io/etcd-amd64:3.4.3docker tag k8s.gcr.io/pause-amd64:3.2 k8s.gcr.io/pause:3.2docker image rm k8s.gcr.io/pause-amd64:3.2
kubeadm init初始化
使用kubeadm init
进行初始化,具体命令如下:
kubeadm init --kubernetes-version=1.18.3 \--apiserver-advertise-address=0.0.0.0 \--image-repository registry.aliyuncs.com/google_containers \--service-cidr=10.96.0.0/12 \--apiserver-cert-extra-sans=XXXX授信IP或域名列表(通过逗号分隔) \--pod-network-cidr=10.244.0.0/16 \ignore-preflight-errors
kubeadm说明参考:https://k8smeetup.github.io/docs/admin/kubeadm/#
执行成功后,根据提示,根据拷贝 admin.conf 文件到当前用户相应目录下。
mkdir -p $HOME/.kubecp -i /etc/kubernetes/admin.conf $HOME/.kube/configchown $(id -u):$(id -g) $HOME/.kube/config
查看集群中node、创建的POD等信息,通过exec -it进入Pod里面
kubectl get pod -n kube-system -o widekubectl get nodes -o widekubectl describe pods -n kube-system $PODNamekubectl exec -it $PODName /bin/bash
kubeadm init初始化流程详细描述如下:
[init]:指定版本进行初始化操作
[preflight] :初始化前的检查和下载所需要的Docker镜像文件
[kubelet-start] :生成kubelet配置文件
/var/lib/kubelet/config.yaml[certs]:生成Kubernetes使用的证书在
/etc/kubernetes/pki
目录。[kubeconfig] :生成 KubeConfig 文件,存放在/etc/kubernetes目录中,组件之间通信需要使用对应文件。
[control-plane]:使用
/etc/kubernetes/manifest
目录下的YAML文件,安装 Master 组件。[etcd]:使用
/etc/kubernetes/manifest/etcd.yaml
安装Etcd服务。[wait-control-plane]:等待control-plan部署的Master组件启动。
[apiclient]:检查Master组件服务状态。
[upload-config]:更新配置
[kubelet]:使用configMap配置kubelet。
[mark-control-plane]:为当前节点打标签,打了角色Master,和不可调度标签,这样默认就不会使用Master节点来运行Pod。
[bootstrap-token]:生成token记录下来,后边使用kubeadm join往集群中添加节点时会用到
[addons]:安装附加组件CoreDNS和kube-proxy
安装pod-network
在安装网络插件之前,运行 kubectl get nodes
展示node的状态是NotReady。下载kube-flannel.yml文件,并安装网络插件:
wget https://github.com/coreos/flannel/edit/master/Documentation/kube-flannel.ymlkubectl apply -f kube-flannel.yml
备注:如果只有Master 主机,集群也可以正常使用的,但默认情况下,出于安全考虑,集群不会在 control-plane 运行节点上部署 pods,如果需要正常使用单节点集群,需要使用如下命令解除该限制:
> kubectl describe nodes master |grep TaintsTaints: node-role.kubernetes.io/master:NoSchedule> kubectl taint node master node-role.kubernetes.io/master-node/master untainted> kubectl describe nodes master |grep TaintsTaints: <none>
节点部署
使用master上的k8s配置文件yaml部署node节点上的POD
使用kubeadm config print init-defaults 2>/dev/null >kubeadm-config.yaml
获取集群初始化默认的使用的配置,基于实际配置对文件进行微调(标+:改后;表-:改前)
apiVersion: kubeadm.k8s.io/v1beta2bootstrapTokens:- groups:- system:bootstrappers:kubeadm:default-node-tokentoken: abcdef.0123456789abcdefttl: 24h0m0susages:- signing- authenticationkind: InitConfigurationlocalAPIEndpoint:- advertiseAddress: 1.2.3.4+ advertiseAddress: 192.168.1.60 #master节点的IPbindPort: 6443nodeRegistration:criSocket: /var/run/dockershim.sock+ name: master #这里可以填写IP地址以及域名,使用域名时,必须保证解析taints:- - effect: NoSchedule+ - effect: PreferNoSchedule #taints污点,key: node-role.kubernetes.io/masterapiServer:timeoutForControlPlane: 4m0sapiVersion: kubeadm.k8s.io/v1beta2certificatesDir: /etc/kubernetes/pkiclusterName: kubernetescontrollerManager: {}dns:type: CoreDNSetcd:local:dataDir: /var/lib/etcd-imageRepository: k8s.gcr.io+imageRepository: registry.cn-hangzhou.aliyuncs.com/google_containers #修改为国内源kind: ClusterConfigurationkubernetesVersion: v1.18.3networking:dnsDomain: cluster.localserviceSubnet: 10.96.0.0/12+ podSubnet: 10.100.0.1/16scheduler: {}
在其他节点上运行
kubeadm init --config kubeadm-config.yaml
进行初始化。成功之后,再安装pod-network网络插件。使用
kubeadm config view
查看集群信息。
加入到集群的命令为:kubeadm join --token <token> <control-plane-host>:<control-plane-port> --discovery-token-ca-cert-hash sha256:<hash>
(12.1)token未过期
默认情况下,kubeadm init成功之后,会默认生成一个token,默认是24小时有效的。如果未过期,可以使用kubeadm token create --print-join-command
来查看。如果使用kubectl get nodes
查看集群,可能会看到node是NotReady的状态(下载images需要较慢导致)
(12.2)token过期
如果超过了24小时,可通过如下命令创建一个新的token。然后在要加的节点上面运行 kubeadm join 192.168.1.60:6443 --token $OUT1 --discovery-token-ca-cert-hash $OUT2 其中OUT1、OUT2分别对应两条命令的输出
kubeadm token create #OUT1openssl x509 -pubkey -in /etc/kubernetes/pki/ca.crt | openssl rsa -pubin -outform der 2>/dev/null | openssl dgst -sha256 -hex | sed 's/^.* //' # OUT2
安装Dashboard
Dashboard 是基于网页的 Kubernetes 用户界面。集成应用部署、容器应用排错、管理集群资源、获取应用的概览信息、创建或修改 Kubernetes 资源。
具体链接:https://github.com/kubernetes/dashboard/tree/master/docs
(13.1)下载yml并通过kubectl apply创建pod
wget https://raw.githubusercontent.com/kubernetes/dashboard/v2.0.0-rc5/aio/deploy/recommended.yamlkubectl apply -f recommended.yaml
注意,目前Dashboard的namespace为
kubernetes-dashboard
。可以运行kubectl get pods -n kubernetes-dashboard
来查看pod的状态。
(13.2)要需要创建RBAC。就是创建权限访问控制。
apiVersion: v1kind: ServiceAccountmetadata:name: admin-usernamespace: kubernetes-dashboard---apiVersion: rbac.authorization.k8s.io/v1kind: ClusterRoleBindingmetadata:name: admin-userroleRef:apiGroup: rbac.authorization.k8s.iokind: ClusterRolename: cluster-adminsubjects:- kind: ServiceAccountname: admin-usernamespace: kubernetes-dashboard
kubectl create -f kubernetes-dashboard-admin.rbac.yamlkubectl create serviceaccount admin-user -n kubernetes-dashboardkubectl create clusterrolebinding admin-user --clusterrole=cluster-admin --serviceaccount=kubernetes-dashboard:admin-user
(13.3)API方式访问。可以使用浏览器访问地址:
https://{master-ip}:6443/api/v1/namespaces/kubernetes-dashboard/services/https:kubernetes-dashboard:/proxy/#/login
这时会要求输入一个token,可以使用使用来获取:kubectl -n kubernetes-dashboard describe secret $(kubectl -n kubernetes-dashboard get secret | grep admin-user | awk '{print $1}')
chrome浏览器不能访问,因SSL证书是自签的,chrome不认,但可以这样做:
grep 'client-certificate-data' ~/.kube/config | head -n 1 | awk '{print $2}' | base64 -d >> kubecfg.crtgrep 'client-key-data' ~/.kube/config | head -n 1 | awk '{print $2}' | base64 -d >> kubecfg.keyopenssl pkcs12 -export -clcerts -inkey kubecfg.key -in kubecfg.crt -out kubecfg.p12 -name "kubernetes-client"
按要求输入密码直接回车即可,密码不要胡乱输,后面给浏览器导入的时候要用。
运行完后在当前目录会有个kubecfg.p12证书文件。该证书文件一次运行,多次使用也可以使用rancher通过helm进行部署,部署成功后重复步骤13.2、13.3
问题现象
events is forbidden: User "system:serviceaccount:kube-system:kube-system-kubernetes-dashboard" cannot list resource "events" in API group "" in the namespace "default"
问题解决
kubectl create clusterrolebinding kube-system-kubernetes-dashboard --clusterrole=cluster-admin --serviceaccount=kube-system:kube-system-kubernetes-dashboard




