千家信息网

部署k8s集群(亲测无坑)

发表于:2024-11-25 作者:千家信息网编辑
千家信息网最后更新 2024年11月25日,kubernetes 简介kubernetes,简称K8s,是一个开源的,用于管理云平台中多个主机上的容器化的应用,Kubernetes的目标是让部署容器化的应用简单并且高效(powerful),Ku
千家信息网最后更新 2024年11月25日部署k8s集群(亲测无坑)

kubernetes 简介
kubernetes,简称K8s,是一个开源的,用于管理云平台中多个主机上的容器化的应用,Kubernetes的目标是让部署容器化的应用简单并且高效(powerful),Kubernetes提供了应用部署,规划,更新,维护的一种机制。


优势:
传统的应用部署方式是通过插件或脚本来安装应用。这样做的缺点是应用的运行、配置、管理、所有生存周期将与当前操作系统绑定,这样做并不利于应用的升级更新/回滚等操作,当然也可以通过创建虚拟机的方式来实现某些功能,但是虚拟机非常重,并不利于可移植性。
新的方式是通过部署容器方式实现,每个容器之间互相隔离,每个容器有自己的文件系统 ,容器之间进程不会相互影响,能区分计算资源。相对于虚拟机,容器能快速部署,由于容器与底层设施、机器文件系统解耦的,所以它能在不同云、不同版本操作系统间进行迁移。
容器占用资源少、部署快,每个应用可以被打包成一个容器镜像,每个应用与容器间成一对一关系也使容器有更大优势,使用容器可以在build或release 的阶段,为应用创建容器镜像,因为每个应用不需要与其余的应用堆栈组合,也不依赖于生产环境基础结构,这使得从研发到测试、生产能提供一致环境。类似地,容器比虚拟机轻量、更"透明",这更便于监控和管理。


▪ Master 组件
▪ 节点(Node)组件
Kubernetes是Google开源的一个容器编排引擎,它支持自动化部署、大规模可伸缩、应用容器化管理。在生产环境中部署一个应用程序时,通常要部署该应用的多个实例以便对应用请求进行负载均衡。
在Kubernetes中,我们可以创建多个容器,每个容器里面运行一个应用实例,然后通过内置的负载均衡策略,实现对这一组应用实例的管理、发现、访问,而这些细节都不需要运维人员去进行复杂的手工配置和处理。


Kubernetes 特点
可移植: 支持公有云,私有云,混合云,多重云(multi-cloud)
可扩展: 模块化,插件化,可挂载,可组合
自动化: 自动部署,自动重启,自动复制,自动伸缩/扩展


Master 组件
1.1kube-apiserver
1.2ETCD
1.3kube-controller-manager
1.4cloud-controller-manager
1.5kube-scheduler
1.6插件 addons
1.6.1DNS
1.6.2用户界面
1.6.3容器资源监测
1.6.4Cluster-level Logging


节点(Node)组件
2.1kubelet
2.2kube-proxy
2.3docker
2.4RKT
2.5supervisord
2.6fluentd


Master 组件
Master组件提供集群的管理控制中心。Master组件可以在集群中任何节点上运行。但是为了简单起见,通常在一台VM/机器上启动所有Master组件,并且不会在此VM/机器上运行用户容器。请参考构建高可用群集以来构建multi-master-VM。


kube-apiserver
kube-apiserver用于暴露Kubernetes API。任何的资源请求/调用操作都是通过kube-apiserver提供的接口进行。请参阅构建高可用群集。


ETCD
etcd是Kubernetes提供默认的存储系统,保存所有集群数据,使用时需要为etcd数据提供备份计划。


kube-controller-manager
kube-controller-manager运行管理控制器,它们是集群中处理常规任务的后台线程。逻辑上,每个控制器是一个单独的进程,但为了降低复杂性,它们都被编译成单个二进制文件,并在单个进程中运行。


这些控制器包括:
节点(Node)控制器。
副本(Replication)控制器:负责维护系统中每个副本中的pod。
端点(Endpoints)控制器:填充Endpoints对象(即连接Services&Pods)。
Service Account和Token控制器:为新的Namespace创建默认帐户访问API Token。


cloud-controller-manager
云控制器管理器负责与底层云提供商的平台交互。云控制器管理器是Kubernetes版本1.6中引入的,目前还是Alpha的功能。
云控制器管理器仅运行云提供商特定的(controller loops)控制器循环。可以通过将--cloud-providerflag设置为external启动kube-controller-manager ,来禁用控制器循环。


cloud-controller-manager 具体功能:
节点(Node)控制器
路由(Route)控制器
Service控制器
卷(Volume)控制器


kube-scheduler
kube-scheduler监视新创建没有分配到Node的Pod,为Pod选择一个Node。
插件 addons
插件(addon)是实现集群pod和Services功能的。Pod由Deployments,ReplicationController等进行管理。Namespace 插件对象是在kube-system Namespace中创建。
DNS
虽然不严格要求使用插件,但Kubernetes集群都应该具有集群 DNS。
群集 DNS是一个DNS服务器,能够为 Kubernetes services提供 DNS记录。
由Kubernetes启动的容器自动将这个DNS服务器包含在他们的DNS searches中。
用户界面
kube-ui提供集群状态基础信息查看。
容器资源监测
容器资源监控提供一个UI浏览监控数据。


Cluster-level Logging
Cluster-level logging,负责保存容器日志,搜索/查看日志。
节点(Node)组件
节点组件运行在Node,提供Kubernetes运行时环境,以及维护Pod。
kubelet
kubelet是主要的节点代理,它会监视已分配给节点的pod,具体功能:
安装Pod所需的volume。
下载Pod的Secrets。
Pod中运行的 docker(或experimentally,rkt)容器。
定期执行容器健康检查。
Reports the status of the pod back to the rest of the system, by creating amirror podif necessary.
Reports the status of the node back to the rest of the system.


kube-proxy
kube-proxy通过在主机上维护网络规则并执行连接转发来实现Kubernetes服务抽象。
docker
docker用于运行容器。
RKT
rkt运行容器,作为docker工具的替代方案。


supervisord
supervisord是一个轻量级的监控系统,用于保障kubelet和docker运行。
fluentd
fluentd是一个守护进程,可提供cluster-level logging.。

集群环境:
系统centos7
master、node
----------------(前期调试在每台进行操作)----------------
设置三台机器的主机名:

master上执行:hostnamectl --static set-hostname k8s-masternode1上执行:hostnamectl --static set-hostname k8s-node-1node2上执行:hostnamectl --static set-hostname k8s-node-2

修改每台hosts文件互解:

cat << EOF >> /etc/hosts 192.168.180.128 k8s-master192.168.180.133 k8s-node-1EOF

关闭防火墙和selinux

systemctl stop firewalld && systemctl disable firewalld && setenforce 0setenforce 0 sed -i 's/^SELINUX=enforcing$/SELINUX=permissive/' /etc/selinux/config

开启linux路由转发功能

echo "1" > /proc/sys/net/ipv4/ip_forward

设置ssh使服务器之间互信

mkdir ~/.sshssh-keygen -t rsassh-copy-id -i ~/.ssh/id_rsa.pub user@server

kubernetes集群组件(需要配置的)
-etcd :一个高可用的K/V键值对存储和服务发现系统
-flannel:实现跨主机的容器网络的通信
-kube-apiserver:提供kubernetes集群的api调用
-kube-controller-manager:确保集群服务
-kube-scheduler调度容器:分配到node
-kubelet:在node节点上按照配置文件中定义的容器规格启动容器
-kube-proxy提供网络代理服务

下载依赖包-lvm2-docker等

yum update -y && yum -y install yum-utils device-mapper-persistent-data lvm2 yum-config-manager --enable docker-ce-nightlyyum-config-manager --enable docker-ce-test

添加官方yum库

sudo yum-config-manager \ --add-repo \ https://download.docker.com/linux/centos/docker-ce.repo

安装docker

sudo yum install docker-ce docker-ce-cli containerd.iosystemctl enable docker && systemctl start dockeryum-config-manager --enable docker-ce-nightlyyum-config-manager --enable docker-ce-test

或者使用脚本一键安装

curl -fsSL "https://get.docker.com/" | shsystemctl enable --now docker

修改docker cgroup驱动,与k8s一致,使用systemd 修改docker cgroup驱动:

native.cgroupdriver=systemdcat > /etc/docker/daemon.json <

所有节点安装/kubeadm/kubelet/kubectl

添加YUM源

-------------------阿里云YUM-------------------

cat > /etc/yum.repos.d/kubernetes.repo << EOF[kubernetes]name=Kubernetesbaseurl=https://mirrors.aliyun.com/kubernetes/yum/repos/kubernetes-el7-x86_64enabled=1gpgcheck=0repo_gpgcheck=0gpgkey=https://mirrors.aliyun.com/kubernetes/yum/doc/yum-key.gpg https://mirrors.aliyun.com/kubernetes/yum/doc/rpm-package-key.gpgEOF

-------------------Google YUM-------------------

cat < /etc/yum.repos.d/kubernetes.repo[kubernetes]name=Kubernetesbaseurl=https://packages.cloud.google.com/yum/repos/kubernetes-el7-x86_64enabled=1gpgcheck=1repo_gpgcheck=1gpgkey=https://packages.cloud.google.com/yum/doc/yum-key.gpg https://packages.cloud.google.com/yum/doc/rpm-package-key.gpgEOF

安装kubelet kubeadm kubectl

yum install -y kubelet kubeadm kubectl --disableexcludes=kubernetessystemctl enable --now kubelet

----------------(master操作)--------------
部署Kubernetes Master

在(Master)执行。

 kubeadm init \  --apiserver-advertise-address=192.168.180.128 \  --image-repository registry.aliyuncs.com/google_containers \  --service-cidr=10.1.0.0/16 \  --pod-network-cidr=10.244.0.0/16

--apiserver-advertise-address 指定与其它节点通信的接口
--pod-network-cidr 指定pod网络子网,使用fannel网络必须使用这个CIDR
--image-repository=registry.aliyuncs.com/google_containers初始化时可以添加下载镜像的源地址。因为默认是google的,国内无法访问。这样前面就不要提前下载好镜像了。

用户设置权限(root用户也需要执行)
master 执行

mkdir -p $HOME/.kubesudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/configsudo chown $(id -u):$(id -g) $HOME/.kube/config

安装Pod网络插件(CNI)
master 执行

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

----------------(node操作)--------------

node节点加入到master

node1:kubeadm join 192.168.1.100:6443 --token te0fvk.dbf7t1qsu4kpvxe2 \--discovery-token-ca-cert-hash sha256:dd74bd1b52313dd8664b8147cb6d18a6f8b25c6c5aa4debc3

结果检查
node节点加入master输出信息如下:

[preflight] Running pre-flight checks[preflight] Reading configuration from the cluster...[preflight] FYI: You can look at this config file with 'kubectl -n kube-system get cm kubeadm-config -oyaml'[kubelet-start] Downloading configuration for the kubelet from the "kubelet-config-1.15" ConfigMap in the kube-system namespace[kubelet-start] Writing kubelet configuration to file "/var/lib/kubelet/config.yaml"[kubelet-start] Writing kubelet environment file with flags to file "/var/lib/kubelet/kubeadm-flags.env"[kubelet-start] Activating the kubelet service[kubelet-start] Waiting for the kubelet to perform the TLS Bootstrap...This node has joined the cluster:* Certificate signing request was sent to apiserver and a response was received.* The Kubelet was informed of the new secure connection details.Run 'kubectl get nodes' on the control-plane to see this node join the cluster.

----------------(master操作)--------------

master 节点执行kubectl get nodes

[root@master ~]# kubectl get nodesNAME     STATUS   ROLES    AGE     VERSIONmaster   Ready    master   14m     v1.15.2node1    Ready       3m36s   v1.15.2node2    Ready       101s    v1.15.2

测试kubernetes集群

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

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

《《 初始化 Kubernetes (端口被占用的问题)
报错信息
[root@k8s-master01 ~]# kubeadm init --config config.yaml

[init] Using Kubernetes version: v1.10.0
[init] Using Authorization modes: [Node RBAC]
[preflight] Running pre-flight checks.
[preflight] Some fatal errors occurred:
[ERROR Port-6443]: Port 6443 is in use
[ERROR Port-10250]: Port 10250 is in use
[ERROR Port-10251]: Port 10251 is in use
[ERROR Port-10252]: Port 10252 is in use
[ERROR FileAvailable--etc-kubernetes-manifests-kube-apiserver.yaml]: /etc/kubernetes/manifests/kube-apiserver.yaml already exists
[ERROR FileAvailable--etc-kubernetes-manifests-kube-controller-manager.yaml]: /etc/kubernetes/manifests/kube-controller-manager.yaml already exists
[ERROR FileAvailable--etc-kubernetes-manifests-kube-scheduler.yaml]: /etc/kubernetes/manifests/kube-scheduler.yaml already exists
[preflight] If you know what you are doing, you can make a check non-fatal with --ignore-preflight-errors=...
解决方案:发现杀死进程都没有用,最终重启一下kubeadm就可以了,如下:
[root@k8s-master01 ~]# kubeadm reset 》》

部署 Dashboard

kubectl apply -f https://raw.githubusercontent.com/kubernetes/dashboard/v1.10.1/src/deploy/recommended/kubernetes-dashboard.yamlwget  https://raw.githubusercontent.com/kubernetes/dashboard/v1.5.1/src/deploy/kubernetes-dashboard.yaml

默认镜像国内无法访问,修改镜像地址为: lizhenliang/kubernetes-dashboard-amd64:v1.10.1

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

vim kubernetes-dashboard.yamlkind: ServiceapiVersion: v1metadata:  labels:    k8s-app: kubernetes-dashboard  name: kubernetes-dashboard  namespace: kube-systemspec:  type: NodePort  ports:    - port: 443      targetPort: 8443      nodePort: 30001  selector:    k8s-app: kubernetes-dashboard
$ kubectl apply -f kubernetes-dashboard.yaml

注意:安装v1.10.1之前先将配置文件中版本信息v1.5.1修改为v1.10.1

docker pull gcr.io/google_containers/kubernetes-dashboard-amd64:v1.10.1

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

$ 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。

使用apiserver方式访问平台

注:自行修改ip以及端口

打开浏览器访问 https://192.168.255.140:8443/api/v1/namespaces/kube-system/services/https:kubernetes-dashboard:/proxy/

报错如下:

{  "kind": "Status",  "apiVersion": "v1",  "metadata": {  },  "status": "Failure",  "message": "services \"https:kubernetes-dashboard\" is forbidden: User \"system:anonymous\" cannot get services/proxy in the namespace \"kube-system\"",  "reason": "Forbidden",  "details": {    "name": "https:kubernetes-dashboard",    "kind": "services"  },  "code": 403}

通过message和code,我们使用的是system:anonymous这样的用户来访问位于kube-system命名空间中的名为https:kubernetes-dashboard的service资源。然后这个用户没有权限访问,所以被拒绝了。

k8s中的用户和认证及授权机制。

k8s中的用户、认证及授权机制简介,k8s中的用户有两种
真实用户 :如kubelet
服务账户: 即service account(简写为sa)
k8s中的认证机制
k8s通过ClusterRoleBinding或者RoleBinding资源来实现对用户权限的赋予。
ClusterRole或者Role:意思是集群角色或角色,他们是规定了一组对集群内资源的权限规则。
roles和clusterroles的区别在于: roles只能对某个命令空间内的资源定义权限。而集群角色定义的权限都是针对整个集群的命名空间的。

将用户和role绑定起来就实现了对用户权限的授予。

创建并导入认证证书
创建证书
首先需要确认kubectl命令的配置文件,默认情况下为/etc/kubernetes/admin.conf,而且已经自动创建在$HOME/.kube/config中,如果没有创建则需要手动赋值。

cat $HOME/.kube/config

如果确认有集群的配置,则运行以下命令来生成一个p12格式的浏览器证书

先生成kubecfg-crt

grep 'client-certificate-data' ~/.kube/config | head -n 1 | awk '{print $2}' | base64 -d >> kubecfg.crt

生成kubecfg-key

grep 'client-key-data' ~/.kube/config | head -n 1 | awk '{print $2}' | base64 -d >> kubecfg.key

生成p12证书,按要求输入密码直接回车即可,密码不要胡乱输,后面给浏览器导入的时候要用。

openssl pkcs12 -export -clcerts -inkey kubecfg.key -in kubecfg.crt -out kubecfg.p12 -name "kubernetes-client"

运行完后在当前目录会有个kubecfg.p12证书文件,将这个kubecfg.p12证书文件传到桌面上,可以通过安装yum install lrzsz,将文件发送到桌面上

[root@master1] ~$ sz kubecfg.p12

将证书导入chrome浏览器

点击浏览器:菜单-设置-高级-管理证书

选择"个人"这一栏(适用于chrome71以上版本,71以下不确定行不行),然后点击导入kubecfg.p12。

剩下的步骤全部默认,完成后如下:

导入成功后,重启浏览器

chrome://restart

注:使用如下链接,更改ip和端口访问再次访问

https://192.168.255.140:8443/api/v1/namespaces/kube-system/services/https:kubernetes-dashboard:/proxy/

此时会弹出类似如下的证书信息对话框,点击确定即可。


点击确定之后,会出现下面的界面

选择登录方式
kubeconfig、令牌、用户名和密码,直接访问,不使用任何登录,使用令牌方式登录,全部资源访问权限,先创建一个账号,再创建一个有全部权限的clusterroles,将二者用clusterrolebinding绑定起来。

安装yaml文件时,已创建了一个名为kubernetes-dashboard的服务账户,查看详情

[root@master2] ~$ kubectl describe serviceaccount/kubernetes-dashboard -n kube-systemName:                kubernetes-dashboardNamespace:           kube-systemLabels:              k8s-app=kubernetes-dashboardAnnotations:         Image pull secrets:  Mountable secrets:   kubernetes-dashboard-token-jwld4Tokens:              kubernetes-dashboard-token-jwld4Events:              

而kubernetes集群安装好后,他会自动生成一些clusterroles集群权限对象,你可以用下面的命令查看都有哪些

[root@master2] ~$ kubectl get  clusterrolesNAME                                                                   AGEadmin                                                                  4h31mcluster-admin                                                          4h31medit                                                                   4h31mflannel                                                                3h68msystem:aggregate-to-admin                                              4h31msystem:aggregate-to-edit                                               4h31m

比如集群管理员,我们详细的看一下,*号表示对所有资源有所有权限。

[root@master2] ~$ kubectl describe  clusterroles/cluster-adminName:         cluster-adminLabels:       kubernetes.io/bootstrapping=rbac-defaultsAnnotations:  rbac.authorization.kubernetes.io/autoupdate: truePolicyRule:  Resources  Non-Resource URLs  Resource Names  Verbs  ---------  -----------------  --------------  -----  *.*        []                 []              [*]             [*]                []              [*]

用户和权限都有了,将他们绑定起来

将kubernetes-dashboard这个服务账户和cluster-admin这个集群管理员权限对象绑定起来。

##13. 创建一个yaml文件, vim dashboard.yaml,内容如下

apiVersion: rbac.authorization.k8s.io/v1beta1kind: ClusterRoleBindingmetadata:  name: kubernetes-dashboard  labels:    k8s-app: kubernetes-dashboardroleRef:  apiGroup: rbac.authorization.k8s.io  kind: ClusterRole  name: cluster-adminsubjects:- kind: ServiceAccount  name: kubernetes-dashboard  namespace: kube-system

执行

[root@master2] ~$ kubectl create -f dashboard.yaml

查看是否创建成功

[root@master2] ~$ kubectl get clusterrolebindings kubernetes-dashboardNAME                   AGEkubernetes-dashboard   88s

找到kubernetes-dashboard账户的token,记下这串token,登录的时候会使用,这个token默认是永久的。

kubectl -n kube-system describe secret $(kubectl -n kube-system get secret | grep kubernetes-dashboard-token | awk '{print $1}')
Name:         kubernetes-dashboard-token-jwld4Namespace:    kube-systemLabels:       Annotations:  kubernetes.io/service-account.name: kubernetes-dashboard              kubernetes.io/service-account.uid: a2ced45f-8b61-11e9-b98f-0050563ff983Type:  kubernetes.io/service-account-tokenDatanamespace:  11 bytestoken:      eyJhbGciOiJSUzI1NiIsImtpZCI6IiJ9.eyJpc3MiOiJrdWJlcm5ldGVzL3NlcnZpY2VhY2NvdW50Iiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9uYW1lc3BhY2UiOiJrdWJlLXN5c3RlbSIsImt1YmVybmV0ZXMuaW8vc2VydmljZWFjY291bnQvc2VjcmV0Lm5hbWUiOiJrdWJlcm5ldGVzLWRhc2hib2FyZC10b2tlbi1qd2xkNCIsImt1YmVybmV0ZXMuaW8vc2VydmljZWFjY291bnQvc2VydmljZS1hY2NvdW50Lm5hbWUiOiJrdWJlcm5ldGVzLWRhc2hib2FyZCIsImt1YmVybmV0ZXMuaW8vc2VydmljZWFjY291bnQvc2VydmljZS1hY2NvdW50LnVpZCI6ImEyY2VkNDVmLThiNjEtMTFlOS1iOThmLTAwNTA1NjNmZjk4MyIsInN1YiI6InN5c3RlbTpzZXJ2aWNlYWNjb3VudDprdWJlLXN5c3RlbTprdWJlcm5ldGVzLWRhc2hib2FyZCJ9.VzsWE80t7AEMB891rxBKJVMxwt5DtuzA23_-SLxxQcjpaB80LBfB09WqUSe6G6vrkRdpMQ3wDLA2SIFCQVAapAHl-J45NuPyhxh8A-DNpfGpEk3uxFqXkn5WXYasbeCIcHw6TII27PTwG6wgS_q1qEbOf4LYJHjExdqypIqAj__F2RRGTqER378qVvJrHJndL5M6W2PhINazLOEqezxKxDRBigMFU7luOYvWCxSPFhjSd3LrsMfWwSRY-Jq5-tUEhsI7uU7Yyb3UIDDiXex-8Mwbida_TgpcIZi6BaEclPygSSfq1a177r97hnxcdv02X9ooOghztSGKM-1bDBWhNgca.crt:     1025 bytes

再次访问dashboard,输入token登录后界面如下;
此时访问dashboard的主体是kubernetes-dashboard这个服务账户,它拥有对集群所有资源的所有使用权限。

通过web方式操作很方便,如下:进行扩缩容

生产环境要对不同的人赋予不同的权限,自定义资源访问权限,用kubeconfig方式登录,每次都要复制token,会比较麻烦

1、先把config文件复制到别的地方

[root@master2] ~$ cp .kube/config .

然后把一个具有全部访问权限的token追加到最后一行。先找出token

kubectl -n kube-system describe secret $(kubectl -n kube-system get secret | grep admin-token | awk '{print $1}') |grep token|tail -1

追加到config中,如下

users:- name: kubernetes-admin  user:    client-certificate-data: LS0tLS1CRUd....    client-key-data: LS0tLS1CRUdJTiBSU......    token: eyJhbGciO... ...

上传到桌面,选择登录

使用用户名密码方式登录,默认情况下用户名密码登录没有启用。

如果没有该参数,默认使用的是匿名用户,并且无法检查提供的凭据是否有效。
原因是Kubernetes 需要有配置

如果要启用用户名和密码验证,必须在apiserver的部署文件中配置参数 --authorization-mode=ABAC和and --basic-auth-file。

然后在dashboard的部署文件中设置authentication-mode = basic。默认情况下,它的设置是--authentication-mode = token。

跳过登录过程,直接访问
添加参数- --enable-skip-login

  containers:  - args:    - --auto-generate-certificates    - --enable-skip-login

官方文档:
https://github.com/kubernetes/dashboard/wiki/Accessing-Dashboard-1.7.X-and-above
https://github.com/kubernetes/dashboard/wiki/Creating-sample-user

0